
#include <stdio.h>
#include <curl/curl.h>

#include "waEncode.h"
#include "waHttpClient.h"

namespace webapp
{
	size_t recvfunction(char *bufptr, size_t size, size_t nitems, void *userp)
	{
		HttpClient::stRecvCtx * ptRecvCtx = (HttpClient::stRecvCtx *) userp;
		ptRecvCtx->m_sRecvBuffer.append( bufptr, size*nitems );
		return size * nitems;
	}


	int curl_debug_callback (CURL * ptCurl, curl_infotype type, char * ptBuf, size_t size, void * userp ) 
	{
		string sSectInfo = "";
		switch (type)
		{
			case CURLINFO_HEADER_OUT:
				sSectInfo = "header out";
				break;
			case CURLINFO_HEADER_IN:
				sSectInfo = "header in";
				break;
			case CURLINFO_DATA_OUT:
				sSectInfo = "data out";
				break;
			case CURLINFO_DATA_IN:
				sSectInfo = "data in";
				break;
			default:
				sSectInfo = "the other";
		}

		printf("--------------%s-----------------\n", sSectInfo.c_str() );
		printf("%s", ptBuf );
		printf("-----------------------------------------\n");
		return 0;
	}

	HttpClient :: HttpClient( const string & url, const string & method, bool isDebug )
	{
		m_ptPost = NULL;
		m_ptLast = NULL;
		m_sPostData = "";
		m_ptCurl = curl_easy_init();
		curl_easy_setopt(m_ptCurl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
		
		if (method == "POST" )
			curl_easy_setopt( m_ptCurl, CURLOPT_POST, 1 );
		
		if ( isDebug )
		{
			curl_easy_setopt( m_ptCurl, CURLOPT_VERBOSE, 1L );
			curl_easy_setopt( m_ptCurl, CURLOPT_DEBUGFUNCTION, curl_debug_callback );
			curl_easy_setopt( m_ptCurl, CURLOPT_DEBUGDATA, &m_tRecvCtx);
		}

		SetUrl( url );
	}

	HttpClient :: ~HttpClient()
	{
		curl_easy_cleanup( m_ptCurl );

		if ( m_ptPost )
			curl_formfree( m_ptPost );
	}

	void HttpClient :: FormAdd( const string & name, const string & content )
	{
		curl_formadd( &m_ptPost, &m_ptLast, CURLFORM_COPYNAME, name.c_str(),
			CURLFORM_COPYCONTENTS, content.c_str(),
			CURLFORM_END);
	}

	void HttpClient :: FormAddBinary( const string & name, const string & filepath, const string & filename )
	{
		curl_formadd( &m_ptPost, &m_ptLast, CURLFORM_COPYNAME, name.c_str(),
			CURLFORM_FILE, filepath.c_str(),
			CURLFORM_END);
	}

	void HttpClient :: SetFormAsPostData()
	{
		curl_easy_setopt( m_ptCurl, CURLOPT_HTTPPOST, m_ptPost );
	}

	void HttpClient :: SetFields( vector< pair<string,string> > & fieldsList )
	{
		m_sPostData = ( fieldsList[0].first + "=" + fieldsList[0].second );
		for ( size_t i=1; i<fieldsList.size(); ++i )
		{
			m_sPostData += "&";
			m_sPostData += fieldsList[i].first + "=" + fieldsList[i].second;
		}

		curl_easy_setopt( m_ptCurl, CURLOPT_POSTFIELDS, m_sPostData.c_str() );
		curl_easy_setopt( m_ptCurl, CURLOPT_POSTFIELDSIZE, m_sPostData.size() );
	}

	void HttpClient :: SetRawPostData( const string & data, const string & contenttype )
	{
		m_sPostData = data;
		
		if ( contenttype.size() > 0 )
		{
			curl_slist *http_headers = NULL;
			string t = "Content-Type: " + contenttype;
			http_headers = curl_slist_append(http_headers, t.c_str() );
			curl_easy_setopt( m_ptCurl, CURLOPT_HTTPHEADER, http_headers);
		}

		curl_easy_setopt( m_ptCurl, CURLOPT_POSTFIELDS, m_sPostData.c_str() );
		curl_easy_setopt( m_ptCurl, CURLOPT_POSTFIELDSIZE, m_sPostData.size() );
	}


	void HttpClient :: Reset()
	{
		curl_easy_reset( m_ptCurl );	
	}

	void HttpClient :: SetUrl( const string & url )
	{
		curl_easy_setopt( m_ptCurl, CURLOPT_URL, url.c_str() );
	}

	int HttpClient :: Execute()
	{
		curl_easy_setopt( m_ptCurl, CURLOPT_WRITEFUNCTION, recvfunction );
		curl_easy_setopt( m_ptCurl, CURLOPT_WRITEDATA, &m_tRecvCtx );

		CURLcode res;
		res = curl_easy_perform( m_ptCurl );
		if(res != CURLE_OK)
		{
			fprintf(stderr, "curl_easy_perform() failed: %s\n",
					curl_easy_strerror(res));
			return -1;
		}
		else
		{

			return 0;
		}
	}

	int HttpClient :: Status()
	{ 
		int retcode = 0;
		CURLcode res = curl_easy_getinfo(m_ptCurl, CURLINFO_RESPONSE_CODE , &retcode); 
		return res == CURLE_OK ? retcode : -1;
	}

	const string & HttpClient :: GetContent()
	{
		return m_tRecvCtx.m_sRecvBuffer;
	}

}
